'use strict';

const Service = require('egg').Service;
const { Sequelize, Op } = require("sequelize");

class NovelService extends Service {
    // 搜索
    async search(params) {
        const {model} = this.app
        let sql = {}, whereSql = {}
        whereSql = {
            novel_name: {
                [Op.like]: `%${params.keyword}%`,
            }
        }
        sql = {
            where: whereSql,
            include: {
                required: false,
                where: {
                    status: 1
                },
                model: model.NovelTag,
                attributes: ['tag_name']
            }
        }
        return await model.Novel.findAll(sql);
    }

    async getList(params) {
        const {model} = this.app

        let sql = {}, whereSql = {}, orderSql = {}
        if (params.type && !params.categoryId) {
            sql = {
                where: { type: params.type }, // WHERE 条件
                attributes: ['id'], // 要查询的表字段
            }
            const result = await model.NovelCategory.findAll(sql)
            params.categoryId = []
            result.map(item => {
                params.categoryId.push(item.id)
            })
        }

        params.categoryId ? whereSql.category_id = params.categoryId : ''
        params.updateStatus ? whereSql.update_status = params.updateStatus: ''
        // 时间
        let limitTime = '', updateTime={}
        const nowDate = (new Date).getTime()/1000
        // 1 三日内 2 一月内 3 半年内 4 半年上
        switch (params.update*1) {
            case 1:
                limitTime = nowDate - 60*60*24*3
                updateTime[Op.gte] = limitTime
                break;
            case 2:
                limitTime = nowDate - 60*60*24*30
                updateTime[Op.gte] = limitTime
                break;
            case 3:
                limitTime = nowDate - 60*60*24*30*6
                updateTime[Op.gte] = limitTime
                break;
            case 4:
                limitTime = nowDate - 60*60*24*30*6
                updateTime[Op.lt] = limitTime
                break;
            default :
                updateTime[Op.lt] = nowDate
                break;
        }
        whereSql.update_time = updateTime
        // 字数
        let countWord = {}
        switch (params.countWord*1) {
            case 1:
                countWord[Op.lte] = 100000
                break;
            case 2:
                countWord[Op.lte] = 1000000
                break;
            case 3:
                countWord[Op.gt] = 1000000
                break;
            default:
                countWord[Op.gt] = -1
                break;
        }
        whereSql.word_number = countWord

        // 排序
        orderSql = [[params.sort, 'DESC']]

        sql = {
            where: whereSql,
            order: orderSql,
            limit: params.num*1, // 返回数据量
            offset: params.num*(params.page-1), // 数据偏移量
        }
        let { count, rows } = await model.Novel.findAndCountAll(sql);
        const pageAll = Math.ceil(count/params.num)
        rows = JSON.parse(JSON.stringify(rows))
        for (let i = 0; i < rows.length ; i++) {
            sql = {
                where: { novel_id: rows[i].id, status: 1 }, // WHERE 条件
                attributes: ['tag_name'], // 要查询的表字段
            }
            const result = await model.NovelTag.findAll(sql)
            rows[i]['novel_tags'] = result
        }
        return {
            page: params.page,
            pageAll: pageAll,
            data: rows
        }

    }
    // 获取分类
    async getCategory(params) {
        const {model} = this.app

        let whereSql = {}
        if (params.type) {
            whereSql = { type: params.type, status: true } // WHERE 条件
        } else {
            whereSql = { status: true } // WHERE 条件
        }
        const sql = {
            where: whereSql, // WHERE 条件
            attributes: ['id','type','cate_name'], // 要查询的表字段
        }
        const result = await model.NovelCategory.findAll(sql)
        return result
    }
    // 获取信息
    async getInfo(params) {
        const {model} = this.app
        const sql = {
            where: { id: params.id},
            include: [
                {
                    model: model.NovelTag,
                    where: {
                        status: 1,
                        add_count: {
                            [Op.gte]: 1
                        }
                    },
                    required: false,
                    attributes: ['tag_name']
                },
                {
                    model: model.NovelCategory,
                    required: false,
                    attributes: ['cate_name']
                },
            ],
        }
        const result = await model.Novel.findOne(sql)
        return result
    }
    // 获取评论列表
    async getDiscussList(params) {
        const {model} = this.app

        let sql = {}, whereSql = {}, orderSql = {}, parentIdSolt = {}

        whereSql.novel_id=params.id

        if (params.score == 1) {
            // 不是null 代表有评分
            whereSql.score = {
                [Op.not]: null
            }
        } else if (params.score == 2) {
            // 只有null 代表无评分
            whereSql.score = {
                [Op.is]: null
            }
        }
        
        // 筛选出主评论
        parentIdSolt[Op.is] = null
        whereSql.parent_id = parentIdSolt

        // 排序
        let sortStr = params.sort

        switch (params.sort) {
            case 'latest':
                sortStr = 'update_time'
                break;
        }

        orderSql = [[sortStr, 'DESC']]
        sql = {
            where: whereSql,
            order: orderSql,
            include: [{
                as: 'userInfo',
                model: model.User,
                attributes: ['name']
            }, {
                as: 'resInfo',
                model: model.User,
                attributes: ['name']
            }],
            attributes: {
                include: [
                    [Sequelize.literal(`(SELECT COUNT(*) FROM praise WHERE praise.target_id = novel_discuss.id AND praise.type = 1 AND praise.status = 1)`), 'dz_num'],
                    [Sequelize.literal(`(SELECT COUNT(*) FROM praise WHERE praise.target_id = novel_discuss.id AND praise.type = 2 AND praise.status = 1)`), 'c_num'],
                    [Sequelize.literal(`(SELECT COUNT(*) FROM novel_discuss AS Discuss WHERE Discuss.parent_id = novel_discuss.id)`), 'reply_num'],
                ]
            },
            limit: params.num*1, // 返回数据量
            offset: params.num*(params.page-1), // 数据偏移量
        }

        const { count, rows } = await model.NovelDiscuss.findAndCountAll(sql);

        const pageAll = Math.ceil(count/params.num)
        return {
            page: params.page,
            pageAll: pageAll,
            data: rows
        }
    }
    // 随机获取评论列表
    async getRandomDiscuss(params) {
        const {model} = this.app
        let sql = {}, whereSql = {}, orderSql = {}, parentIdSolt = {}

        whereSql.score = {
            [Op.not]: null
        }
        
        // 筛选出主评论
        parentIdSolt[Op.is] = null
        whereSql.parent_id = parentIdSolt

        orderSql = [Sequelize.literal('rand()')]
        
        sql = {
            where: whereSql,
            order: orderSql,
            limit: params.num*1, // 返回数据量
            offset: params.num*(params.page-1), // 数据偏移量
        }
        let { count, rows } = await model.NovelDiscuss.findAndCountAll(sql);
        rows = JSON.parse(JSON.stringify(rows))
        for (let i = 0; i < rows.length ; i++) {
            // 查用户
            sql = {
                where: { id: rows[i].user_id }, // WHERE 条件
                attributes: ['name', 'head_img_url', 'id'], // 要查询的表字段
            }
            let result = await model.User.findOne(sql)
            rows[i]['userInfo'] = result
            // 查书籍
            sql = {
                where: { id: rows[i].novel_id }, // WHERE 条件
                attributes: ['novel_name', 'id'], // 要查询的表字段
            }
            result = await model.Novel.findOne(sql)
            rows[i]['novelInfo'] = result
            // 查赞
            sql = {
                where: { target_id: rows[i].id, type: 1, status: 1 }, // WHERE 条件
            }
            result = await model.Praise.count(sql)
            rows[i]['dz_num'] = result
            // 查踩
            sql = {
                where: { target_id: rows[i].id, type: 2, status: 1 }, // WHERE 条件
            }
            result = await model.Praise.count(sql)
            rows[i]['c_num'] = result
            // 查回复
            sql = {
                where: { parent_id: rows[i].id }, // WHERE 条件
            }
            result = await model.NovelDiscuss.count(sql)
            rows[i]['reply_num'] = result
        }
        const pageAll = Math.ceil(count/params.num)
        return {
            page: params.page,
            pageAll: pageAll,
            data: rows
        }
    }
    // 获取用户评论详情
    async getDiscussInfo(params) {
        const {model} = this.app
        const sql = {
            where: {
                novel_id: params.novelId,
                user_id: params.userId,
                score: {
                    [Op.not]: null
                }
            }
        }
        return await model.NovelDiscuss.findOne(sql)
    }

    // 发布书籍评论
    async postDiscuss(params) {
        const {model} = this.app
        const { service } = this.ctx;
        const userId = params.userId

        // 1 发布评论(评分和吐槽) 2修改评分
        if (params.type == 1) {
            const sql = {
                where: {
                    score: {
                        [Op.not]: null
                    },
                    novel_id: params.novelId*1,
                    user_id: params.userId,
                }
            }
            const res = await model.NovelDiscuss.findOne(sql)
            if (res && params.score) throw { code: '02', msg: '不能重复评分' }
        } else {
            if (params.score < 2) throw { code: '02', msg: '修改的评分不能小于2' }
            const updateSql = {
                score: params.score,
                content: params.content,
                update_time: (new Date).getTime()/1000
            }
            const sql = {
                where: {
                    novel_id: params.novelId*1,
                    user_id: params.userId,
                    score: {
                        [Op.not]: null
                    }
                }
            }
            return await model.NovelDiscuss.update(updateSql ,sql)
        }

        const userInfo = await model.User.findByPk(userId)

        const sql = {
            novel_id: params.novelId,
            user_id: userId,
            score: params.score,
            score_level: userInfo.score_level,
            content: params.content,
            create_time: (new Date).getTime()/1000,
            update_time: (new Date).getTime()/1000
        }
        const result = await model.NovelDiscuss.create(sql)
        // 第一次给书籍 评分
        if (params.score) service.task.discuss({taskId: 2, userId, desc: '评分任务'});
        return result
    }

    // 修改书籍标签
    async editTag(params) {
        const {model} = this.app

        let result = {}
        // 建立事务对象
        let transaction;
        try {
            transaction = await model.transaction();
            // 增加
            if (params.type == 1) {
                let sql = {
                    where: {
                        tag_name: params.tagName,
                        novel_id: params.novelId,
                        user_id: params.userId
                    },
                    transaction: transaction
                }

                result = await model.UserNovelTag.findOrCreate(sql)
                if (!result[1]) throw { code: '02', msg: '该小说以添加该标签' }

                sql = {
                    where: {
                        tag_name: params.tagName,
                        novel_id: params.novelId
                    },
                    defaults: {
                        add_count: 1,
                        update_time: (new Date).getTime()/1000
                    },
                    transaction: transaction
                }
                
                result = await model.NovelTag.findOrCreate(sql)
                // 已存在
                if (!result[1]) {
                    // 事务改操作
                    await model.NovelTag.update({
                        add_count: model.literal('add_count+1') 
                    }, {
                        where: {
                            tag_name: params.tagName,
                            novel_id: params.novelId,
                        },
                        transaction: transaction,
                    });
                }
            } else {
                // 删除
                // 事务改操作
                await model.UserNovelTag.update({
                    status: 0
                }, {
                    where: {
                        tag_name: params.tagName,
                        novel_id: params.novelId,
                        user_id: params.userId
                    },
                    transaction: transaction,
                });

                // 事务改操作
                await model.NovelTag.update({
                    add_count: model.literal('add_count-1') 
                }, {
                    where: {
                        tag_name: params.tagName,
                        novel_id: params.novelId,
                    },
                    transaction: transaction,
                });

            }

            // 提交事务
            await transaction.commit();

            return result
        } catch (error) {
            console.log(error)
            // 事务回滚
            await transaction.rollback();
            throw error;
        }
    }

    // 获取用户小说标签
    async getUserTagList(params) {
        const {model} = this.app
        const sql = {
            where: { 
                novel_id: params.novelId,
                user_id: params.userId,
                status: 1
            }
        }
        const result = await model.UserNovelTag.findAll(sql)
        return result
    }
}

module.exports = NovelService;
